﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.ServiceModel;

namespace NntpTransport
{
	public abstract class NntpChannelBase : ChannelBase
	{
		const int _MaxBufferSize = 64 * 1024;
		const int _MaxSizeOfHeaders = 4 * 1024;
		readonly EndpointAddress _Address;
		readonly BufferManager _BufferManager;
		readonly MessageEncoder _Encoder;
		readonly long _MaxReceivedMessageSize;
		readonly bool _Streamed;

		public NntpChannelBase(BufferManager BufferManager, MessageEncoderFactory EncoderFactory,
			EndpointAddress Address, ChannelManagerBase Parent, bool Streamed, long MaxReceivedMessageSize)
			: base(Parent)
		{
			this._Address = Address;
			this._BufferManager = BufferManager;
			this._Encoder = EncoderFactory.CreateSessionEncoder();
			this._MaxReceivedMessageSize = MaxReceivedMessageSize;
			this._Streamed = Streamed;
		}

		protected Message ReadMessage(string path)
		{
			if(this._Streamed)
			{
				return StreamedReadMessage(path);
			}
			return BufferedReadMessage(path);
		}

		protected void WriteMessage(string path, Message message)
		{
			if(this._Streamed)
			{
				StreamedWriteMessage(path, message);
			}
			else
			{
				BufferedWriteMessage(path, message);
			}
		}

		public EndpointAddress RemoteAddress
		{
			get { return this._Address; }
		}

		#region Read/Write

		Message BufferedReadMessage(string path)
		{
			throw new NotImplementedException();

			//byte[] data; long bytesTotal; try
			//{
			//    using(FileStream stream = new FileStream(path, FileMode.Open))
			//    {
			//        bytesTotal = stream.Length;
			//        if(bytesTotal > int.MaxValue)
			//        {
			//            throw new CommunicationException(String.Format("Message of size {0} bytes is too large to buffer. Use a streamed transfer instead.", bytesTotal));
			//        }
			//        if(bytesTotal > this.maxReceivedMessageSize)
			//        {
			//            throw new CommunicationException(String.Format("Message exceeds maximum size: {0} > {1}.", bytesTotal, maxReceivedMessageSize));
			//        }
			//        data = this.bufferManager.TakeBuffer((int)bytesTotal);
			//        int bytesRead = 0;
			//        while(bytesRead < bytesTotal)
			//        {
			//            int count = stream.Read(data, bytesRead, (int)bytesTotal - bytesRead);
			//            if(count == 0)
			//            {
			//                throw new CommunicationException(String.Format("Unexpected end of message after {0} of {1} bytes.", bytesRead, bytesTotal));
			//            } bytesRead += count;
			//        }
			//    }
			//}
			//catch(IOException exception)
			//{
			//    throw ConvertException(exception);
			//}
			//ArraySegment<byte> buffer = new ArraySegment<byte>(data, 0, (int)bytesTotal);
			//return this.encoder.ReadMessage(buffer, this.bufferManager);
		}

		void BufferedWriteMessage(string path, Message message)
		{
			throw new NotImplementedException();
			//ArraySegment<byte> buffer; using(message)
			//{
			//    this.address.ApplyTo(message); buffer = this.encoder.WriteMessage(message, MaxBufferSize, this.bufferManager);
			//}
			//try
			//{
			//    using(FileStream stream = new FileStream(path, FileMode.Create))
			//    {
			//        stream.Write(buffer.Array, buffer.Offset, buffer.Count);
			//    }
			//}
			//catch(IOException exception)
			//{
			//    throw ConvertException(exception);
			//}
		}

		Message StreamedReadMessage(string path)
		{
			throw new NotImplementedException();
			//try
			//{
			//    Stream stream = File.Open(path, FileMode.Open);
			//    long bytesTotal = stream.Length;
			//    if(bytesTotal > maxReceivedMessageSize)
			//    {
			//        throw new CommunicationException(String.Format("Message exceeds maximum size: {0} > {1}.", bytesTotal, maxReceivedMessageSize));
			//    }
			//    return this.encoder.ReadMessage(stream, MaxSizeOfHeaders);
			//}
			//catch(IOException exception)
			//{
			//    throw ConvertException(exception);
			//}
		}
		void StreamedWriteMessage(string path, Message message)
		{
			throw new NotImplementedException();
			//using(message)
			//{
			//    this.address.ApplyTo(message);
			//    try
			//    {
			//        using(Stream stream = File.Open(path, FileMode.Create))
			//        {
			//            this.encoder.WriteMessage(message, stream);
			//        }
			//    }
			//    catch(IOException exception)
			//    {
			//        throw ConvertException(exception);
			//    }
			//}
		}

		#endregion




		protected override void OnAbort()
		{
			throw new NotImplementedException();
		}

		protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
		{
			throw new NotImplementedException();
		}

		protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
		{
			throw new NotImplementedException();
		}

		protected override void OnClose(TimeSpan timeout)
		{
			throw new NotImplementedException();
		}

		protected override void OnEndClose(IAsyncResult result)
		{
			throw new NotImplementedException();
		}

		protected override void OnEndOpen(IAsyncResult result)
		{
			throw new NotImplementedException();
		}

		protected override void OnOpen(TimeSpan timeout)
		{
			throw new NotImplementedException();
		}


	}
}
